using System;
using System.Collections;
using System.Drawing;
using System.Windows.Forms;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;


namespace MetaWorld
{


	/// <summary>
	/// Specialized SceneGraphNode for displaying a mesh object without a texture.
	/// Children must populate the Mesh and SubsetCount objects in their Begin override.
	/// </summary>
	abstract public class SolidMeshObject : SceneGraphNode
	{
		/// <summary>
		/// Internal: reference to the mesh data
		/// </summary>
		protected Mesh Mesh;

		/// <summary>
		/// Internal: number of subsets in mesh data
		/// </summary>
		protected int SubsetCount;

		/// <summary>
		/// Constructor.
		/// </summary>
		public SolidMeshObject () : base () { }

		/// <summary>
		/// Renders the simple object within the given scene
		/// </summary>
		public override void RenderSelf () 
		{
			for (int i = 0; i < this.SubsetCount; i++)
			{
				Mesh.DrawSubset (i);
			}
			base.RenderSelf ();
		}

		/// <summary>
		/// Mesh deinitialization.
		/// </summary>
		public override void End()
		{
			Mesh = null;
			base.End ();
		}

	}

	/// <summary>
	/// Solid-colored unit cube.
	/// </summary>
	public class SolidBox : SolidMeshObject 
	{
		/// <summary>
		/// Constructor.
		/// </summary>
		public SolidBox () : base () { }

		/// <summary>
		/// Initialize the mesh
		/// </summary>
		/// <param name="scene"></param>
		public override void Begin (Scene scene)
		{
			base.Begin (scene);
			Mesh = Mesh.Box (scene.Device, 1f, 1f, 1f);
			SubsetCount = 1;
		}

	}

	
	/// <summary>
	/// Solid-colored unit polygon.
	/// </summary>
	public class SolidPolygon : SolidMeshObject 
	{
		/// <summary>
		/// Constructor.
		/// </summary>
		public SolidPolygon (int sides) : base () 
		{ 
			Sides = sides;
		}

		/// <summary>
		/// Number of sides on the polygon
		/// </summary>
		protected int Sides;

		/// <summary>
		/// Initialize the mesh
		/// </summary>
		/// <param name="scene"></param>
		public override void Begin (Scene scene)
		{
			base.Begin (scene);
			Mesh = Mesh.Polygon (scene.Device, 1f, Sides);
			SubsetCount = 1;
		}
	}

	/// <summary>
	/// Unit sphere object
	/// </summary>
	public class SolidSphere : SolidMeshObject 
	{

		/// <summary>
		/// Mesh level of detail; higher LOD means more facets
		/// </summary>
		protected int LevelOfDetail;

		/// <summary>
		/// Constructor. Higher LevelOfDetail means more facets.
		/// </summary>
		public SolidSphere (int levelOfDetail) : base () 
		{ 
			LevelOfDetail = levelOfDetail;
		}

		/// <summary>
		/// Constructor
		/// </summary>
		public SolidSphere () : this (10) { }

		/// <summary>
		/// Initialize the mesh
		/// </summary>
		/// <param name="scene"></param>
		public override void Begin (Scene scene)
		{
			base.Begin (scene);
			Mesh = Mesh.Sphere (scene.Device, 1f, LevelOfDetail, LevelOfDetail);
			SubsetCount = 1;
		}

	}

	
	/// <summary>
	/// Cylinder of unit length.
	/// </summary>
	public class SolidCylinder : SolidMeshObject 
	{
		/// <summary>
		/// Constructor. Higher LevelOfDetail means more facets. 
		/// The two radii are for cylinder end-points, and they can be different.
		/// </summary>
		/// <param name="levelOfDetail"></param>
		/// <param name="radius1"></param>
		/// <param name="radius2"></param>
		public SolidCylinder (int levelOfDetail, double radius1, double radius2) : base ()
		{
			this.LevelOfDetail = levelOfDetail;
			this.FirstRadius = radius1;
			this.SecondRadius = radius2;
		}

		/// <summary>
		/// Higher level of detail means more facets.
		/// </summary>
		protected int LevelOfDetail;

		/// <summary>
		/// Radius for the first end point
		/// </summary>
		protected double FirstRadius;

		/// <summary>
		/// Radius for the second end point
		/// </summary>
		protected double SecondRadius;

		/// <summary>
		/// Constructor. Higher LevelOfDetail means more facets.
		/// </summary>
		/// <param name="levelOfDetail"></param>
		public SolidCylinder (int levelOfDetail) : 
			this (levelOfDetail, 1, 1) {	}

		/// <summary>
		/// Constructor.
		/// </summary>
		public SolidCylinder () : this (10) { }

		/// <summary>
		/// Initialization function, called before rendering.
		/// </summary>
		/// <param name="scene"></param>
		public override void Begin(Scene scene)
		{
			base.Begin (scene);
			SubsetCount = 1;
			Mesh = Mesh.Cylinder (scene.Device, 
				(float) FirstRadius, 
				(float) SecondRadius, 
				1f, LevelOfDetail, LevelOfDetail);
		}

	}

	
	/// <summary>
	/// Unit torus.
	/// </summary>
	public class SolidTorus : SolidMeshObject 
	{

		/// <summary>
		/// Higher level of detail means more facets.
		/// </summary>
		protected int LevelOfDetail;

		/// <summary>
		/// Radius for the cross-section
		/// </summary>
		protected double InnerRadius;

		/// <summary>
		/// Radius for the hole
		/// </summary>
		protected double OuterRadius;

		/// <summary>
		/// Count for the linear segments of the torus
		/// </summary>
		protected int Segments;

		/// <summary>
		/// Constructor. Higher Segments count means more linear segments 
		/// making up the torus; higher LevelOfDetail means more facets per segment.
		/// Inner radius is the radius of the cross-section. Outer radius is
		/// the radius of the central hole.
		/// </summary>
		/// <param name="segments"></param>
		/// <param name="levelOfDetail"></param>
		/// <param name="innerRadius"></param>
		/// <param name="outerRadius"></param>
		public SolidTorus (int segments, int levelOfDetail, double innerRadius, double outerRadius) : base ()
		{
			LevelOfDetail = levelOfDetail;
			InnerRadius = innerRadius;
			OuterRadius = outerRadius;
			Segments = segments;
		}
		
		/// <summary>
		/// Constructor. Higher LevelOfDetail means more facets.
		/// Inner radius is the radius of the cross-section. Outer radius is
		/// the radius of the central hole.
		/// </summary>
		/// <param name="levelOfDetail"></param>
		/// <param name="innerRadius"></param>
		/// <param name="outerRadius"></param>
		public SolidTorus (int levelOfDetail, double innerRadius, double outerRadius) : 
			this (levelOfDetail, levelOfDetail, innerRadius, outerRadius) { }

		/// <summary>
		/// Unit torus constructor. Higher LevelOfDetail means more facets.
		/// </summary>
		/// <param name="levelOfDetail"></param>
		public SolidTorus (int levelOfDetail) : this (levelOfDetail, 1, 1) { }

		/// <summary>
		/// Unit torus constructor.
		/// </summary>
		public SolidTorus () : this (10) { }

		/// <summary>
		/// Initialize the mesh
		/// </summary>
		/// <param name="scene"></param>
		public override void Begin(Scene scene)
		{
			base.Begin (scene);
			SubsetCount = 1;
			Mesh = Mesh.Torus (scene.Device, (float) InnerRadius, (float) OuterRadius, LevelOfDetail, Segments);
		}

	}

	

}